﻿
#define VERBOSE

using System;
using System.Net.NetworkInformation;
using System.Management;
using System.Windows.Forms;

class ProgramContext : ApplicationContext
{
  public ProgramContext( )
  {
   
    // Try to load settings

    Settings settings = new Settings();
    //settings.Reload();
    string wireless = settings.WirelessName;
    string ethernet = settings.WiredName;

    #if VERBOSE
    if ( wireless == "" )
    {
      Console.WriteLine("SETTINGS: No default wireless adapter found");
    }

    if ( ethernet == "" )
    {
      Console.WriteLine("SETTINGS: No default ethernet adapter found");
    }
    #endif

    // If settings are found, try to get the adapter objects

    if ( wireless != "" )
    {
      wirelessObject = FindNetByName( wireless );
    }

    if ( ethernet != "" )
    {
      ethernetObject = FindNetByName( ethernet );
    }
    
    // If the adapter objects don't exist, display error

    if ( wireless != "" && wirelessObject == null )
    {
      Console.WriteLine("ERROR: Couldn't find wireless adapter \"{0}\" from saved settings.", wireless);
    }
    if ( ethernet != "" && ethernetObject == null )
    {
      Console.WriteLine("ERROR: Couldn't find wired adapter \"{0}\" from saved settings.", ethernet);
    }

    #if VERBOSE
    if ( wirelessObject != null )
    {
      Console.WriteLine("SETTINGS: Loaded and found adapter \"{0}\"", wireless);
    }
    if ( ethernetObject != null )
    {
      Console.WriteLine("SETTINGS: Loaded and found adapter \"{0}\"", ethernet);
    }
    #endif

    // If settings aren't found, search for adapters

    if ( wirelessObject == null || ethernetObject == null )
    {
      FindAdapters();

      settings.WirelessName = (string)wirelessObject["Name"];
      settings.WiredName = (string)ethernetObject["Name"];
      settings.Save();
    }

    OnAddressChanged( this, new EventArgs() );

    NetworkChange.NetworkAddressChanged += OnAddressChanged;

  }

  private static void FindAdapters( )
  {
    NetworkInterfaceHelper interfaces = new NetworkInterfaceHelper();

    while ( wirelessObject == null )
    {
      NetworkInterface wirelessInterface =
        interfaces.FindInterfaceByType(NetworkInterfaceType.Wireless80211);

      if ( wirelessInterface == null )
      {
        Console.WriteLine("Please enable your wireless adapter and press any key.");
        Console.ReadKey();
        interfaces = new NetworkInterfaceHelper();
      }
      else
      {
        wirelessObject = FindNetByName(wirelessInterface.Description);
        if ( wirelessObject == null )
          Console.WriteLine("WMI Error: Unable to find adapter {0}", wirelessInterface.Name);
      }
    }

    while ( ethernetObject == null )
    {
      NetworkInterface ethernetInterface =
        interfaces.FindInterfaceByType(NetworkInterfaceType.Ethernet);

      if ( ethernetInterface == null )
      {
        Console.WriteLine("Please enable your ethernet adapter and press any key.");
        Console.ReadKey();
        interfaces = new NetworkInterfaceHelper();
      }
      else
      {
        ethernetObject = FindNetByName(ethernetInterface.Description);
        if ( ethernetObject == null )
          Console.WriteLine("WMI Error: Unable to find adapter {0}", ethernetInterface.Name);
      }
    }

    #if VERBOSE
    WMIHelper.WriteNetInformation(ethernetObject);
    Console.WriteLine();
    WMIHelper.WriteNetInformation(wirelessObject);
    Console.WriteLine();
    #endif
  }

  // APPLICATION ENTRY POINT //

  [System.STAThread]
  static void Main(string[] args)
  {
    ProgramContext program = new ProgramContext();
    Application.Run(program);
  }

  static ManagementObject FindNetByName(string name)
  {
    using ( ManagementClass adapterManager = new ManagementClass("Win32_NetworkAdapter") )
    {
      ManagementObjectCollection adapterCollection = adapterManager.GetInstances();
      foreach ( ManagementObject adapter in adapterCollection )
      {
        object adapterMAC = adapter["Name"];
        if ( adapterMAC != null && adapterMAC.ToString() == name )
          return adapter;
      }
    }

    return null;
  }

  // ADAPTER LOGIC //

  static void OnAddressChanged( object sender, EventArgs e )
  {
    // Re-check the current network status

    ethernetObject.Get();
    wirelessObject.Get();

    #if VERBOSE
    Console.WriteLine("Address change detected...\n");
    WMIHelper.WriteNetInformation(ethernetObject);
    Console.WriteLine();
    WMIHelper.WriteNetInformation(wirelessObject);
    Console.WriteLine();
    #endif

    if ( ethernetObject == null )
    {
      Console.WriteLine("ERROR: No ethernet adapter detected.");
      return;
    }

    if ( wirelessObject == null )
    {
      Console.WriteLine("ERROR: No wireless adapter detected.");
      return;
    }

    UInt16 ethernetStatus = (UInt16)ethernetObject["NetConnectionStatus"];
    UInt16 wirelessStatus = (UInt16)wirelessObject["NetConnectionStatus"];

    if ( ethernetStatus == (UInt16)NetConnectionStatus.Code.Connected &&
         wirelessStatus != (UInt16)NetConnectionStatus.Code.Disconnected )
    {
      #if VERBOSE
        Console.WriteLine("Disabling the wireless adapter.");
      #endif
      UInt32 code = WMIHelper.Disable(wirelessObject);
      if (code == 0)
        Console.WriteLine("Disabled the adapter {0}", wirelessObject["Name"]);
      else
        Console.WriteLine("ERROR: Failed to disable the adapter {0} with code {1}\n", wirelessObject["Name"], code);
    }
    else if ( ethernetStatus == (UInt16)NetConnectionStatus.Code.MediaDisconnected &&
              wirelessStatus == (UInt16)NetConnectionStatus.Code.Disconnected )
    {
      #if VERBOSE
        Console.WriteLine("Enabling the wireless adapter.");
      #endif
      UInt32 code = WMIHelper.Enable(wirelessObject);
      if ( code == 0 )
        Console.WriteLine("Enabled the adapter {0}", wirelessObject["Name"]);
      else
        Console.WriteLine("ERROR: Failed to enable the adapter {0} with code {1}\n", wirelessObject["Name"], code);
    }
  }

  static void OnApplicationShutdown( object sender, EventArgs e )
  {
    WMIHelper.Enable( wirelessObject );
  }

  static ManagementObject wirelessObject;
  static ManagementObject ethernetObject;

}

class NetConnectionStatus
{
  public NetConnectionStatus(UInt16 code)
  {
    this.code = code;
  }

  public override string ToString()
  {
    switch ( code )
    {
      case 0:
        return "Disconnected";
      case 1:
        return "Connecting";
      case 2:
        return "Connected";
      case 3:
        return "Disconnecting";
      case 4:
        return "Hardware Not Present";
      case 5:
        return "Hardware Not Enabled";
      case 6:
        return "Hardware Malfunction";
      case 7:
        return "Media Disconnected";
      case 8:
        return "Authenticating";
      case 9:
        return "Authentication Succeeded";
      case 10:
        return "Authentication Failed";
      case 11:
        return "Invalid Address";
      case 12:
        return "Credentials Required";
      default:
        return null;
    }
  }

  public enum Code : ushort
  {
    Disconnected = 0,
    Connecting = 1,
    Connected = 2,
    Disconnecting = 3,
    HardwareNotPresent = 4,
    HardwareNotEnabled = 5,
    HardwareMalfunction = 6,
    MediaDisconnected = 7,
    Authenticating = 8,
    AuthenticationSucceeded = 9,
    AuthenticationFailed = 10,
    InvalidAddress = 11,
    CredentialsRequired = 12
  }

  UInt16 code;
}

